package bean_factory

import (
	. "gitee.com/kristas/booting-go/framework/core/bean"
	"gitee.com/kristas/booting-go/framework/core/log"
)

func init() {
	processors = append(processors, new(beanPostProcessor))
}

type beanPostProcessor struct {
	PostProcessorBeans []PostProcessorBean `wire:""`
	Log                log.Logger          `wire:""`
}

func (b *beanPostProcessor) Filter(bean Bean) bool {
	return true
}

func (b *beanPostProcessor) Do(bean Bean) error {
	beanName := GetBeanName(bean)
	// before process
	err := b.applyBeanPostProcessorsBeforeInitialization(bean, beanName)
	if err != nil {
		return err
	}
	// initialingBean process
	err = b.initialingProcess(bean)
	if err != nil {
		return err
	}
	// after process
	err = b.applyBeanPostProcessorsAfterInitialization(bean, beanName)
	if err != nil {
		return err
	}
	bean.BeanStart()
	return nil
}

func (b *beanPostProcessor) Order() int {
	return orderBeanPostProcessor
}

func (b *beanPostProcessor) applyBeanPostProcessorsBeforeInitialization(bean Bean, beanName string) error {
	for _, ppb := range b.PostProcessorBeans {
		err := ppb.PostProcessorBeforeInitialization(bean, beanName)
		if err != nil {
			return err
		}
	}
	return nil
}

func (b *beanPostProcessor) initialingProcess(bean Bean) error {
	if initialingBean, ok := bean.(InitialingBean); ok {
		err := initialingBean.Init()
		if err != nil {
			return err
		}
		b.Log.Trace(traceLog(bean, "Init()"))
	}
	return nil
}

func (b *beanPostProcessor) applyBeanPostProcessorsAfterInitialization(bean Bean, beanName string) error {
	for _, ppb := range b.PostProcessorBeans {
		err := ppb.PostProcessorAfterInitialization(bean, beanName)
		if err != nil {
			return err
		}
	}
	return nil
}
